/**
 * @file filter
 * @author liaoxuezhi@baidu.com
 */
/* eslint fecs-indent: [0, "space", 2, 2] */

import * as React from 'react';
import {
  Component,
  PropTypes
} from 'react';
import {render} from '../../renderer';
import {Enhance as FormItem} from '../form-item';
import * as isPlainObject from 'lodash/isPlainObject';
import * as cx from 'classnames';
import * as assign from 'object-assign';
import {ComboForm} from '../combo/combo-form';
import {isEmptyObject} from '../../util';
import {confirm} from '../../../widgets/alert/alert';
import * as findLast from 'lodash/findLast';

@FormItem({
  type: 'table'
})
export default class FormTable extends Component {
  static propTypes = {
    inputClassName: PropTypes.string
  };

  static defaultProps = {
    value: '',
    placeholder: '暂无',
    columns: [],
    addButtonClassName: 'btn-default btn-xs rounded',
    editButtonClassName: 'btn-default btn-xs rounded',
    deleteButtonClassName: 'btn-danger btn-xs rounded',
    confirmButtonClassName: 'btn-info btn-xs rounded',
    cancelButtonClassName: 'btn-default btn-xs rounded',
    addable: false,
    editable: false,
    deletable: false,
    movable: false,
    maxLength: 0,
    minLength: 0
  };

  constructor(props) {
    super(props);

    this.insertRow = this.insertRow.bind(this);
    this.editRow = this.editRow.bind(this);
    this.confirmEdit = this.confirmEdit.bind(this);
    this.cancelEdit = this.cancelEdit.bind(this);
    this.removeRow = this.removeRow.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.state = {
      columns: this.buildColumns(props),
      editIndex: -1
    }
  }

  componentWillReceiveProps(nextProps) {
    const props = this.props;

    if (
      props.addable !== nextProps.addable
      || props.editable !== nextProps.editable
      || props.deletable !== nextProps.deletable
      || props.formItemValue !== nextProps.formItemValue
    ) {
      this.setState({
        columns: this.buildColumns(nextProps),
        editIndex: -1
      });
    }
  }

  buildColumns(props) {
    const columns = (props.columns || []).concat();
    const buttons = [];
    const value = props.getValue() || [];

    if (props.addable && (!props.maxLength || value.length < props.maxLength)) {
      buttons.push({
        icon: 'fa fa-plus',
        type: 'button',
        size: 'sm',
        visibleOn: '!$editing',
        className: `btn m-xs ${props.addButtonClassName}`,
        _onClick: (_, __, index) => this.insertRow(index + 1)
      })
    }

    if (props.editable) {
      buttons.push({
        icon: 'fa fa-pencil',
        type: 'button',
        size: 'sm',
        visibleOn: '!$editing',
        className: `btn m-xs ${props.editButtonClassName}`,
        _onClick: (_, __, index) => this.editRow(index)
      });

      buttons.push({
        icon: 'fa fa-check',
        type: 'button',
        size: 'sm',
        visibleOn: '$editing',
        className: `btn m-xs ${props.confirmButtonClassName}`,
        _onClick: this.confirmEdit
      });

      buttons.push({
        icon: 'fa fa-times',
        type: 'button',
        size: 'sm',
        visibleOn: '$editing',
        className: `btn m-xs ${props.cancelButtonClassName}`,
        _onClick: this.cancelEdit
      });
    }

    if (props.deletable && (!props.minLength || value.length > props.minLength)) {
      buttons.push({
        icon: 'fa fa-minus',
        type: 'button',
        visibleOn: '!$editing',
        size: 'sm',
        className: `btn m-xs ${props.deleteButtonClassName}`,
        _onClick: (_, __, index) => this.removeRow(index)
      })
    }


    if (buttons.length) {
      const operation = findLast(columns, item => item.type === 'operation');

      if (operation) {
        operation.buttons = Array.isArray(operation.buttons) ? operation.buttons.push(...buttons) : buttons;
      } else {
        columns.push({
          type: 'operation',
          label: '操作',
          width: 150,
          buttons
        });
      }
    }


    return columns;
  }

  insertRow(index = 0) {
    const {
      getValue,
      setValue
    } = this.props;

    let value = getValue();
    isPlainObject(value) && (value = [value]);
    let rows = Array.isArray(value) ? value.concat() : [];

    rows.splice(index, 0, {});
    setValue(rows);
  }

  editRow(index) {
    const {
      getValue
    } = this.props;

    let value = getValue();
    isPlainObject(value) && (value = [value]);
    let rows = Array.isArray(value) ? value.concat() : [];


    this.setState({
      editIndex: index,
      editData: rows[index] || {}
    });
  }

  confirmEdit() {
    const {editIndex, editData} = this.state;
    const {
      getValue,
      setValue
    } = this.props;

    let value = getValue();
    isPlainObject(value) && (value = [value]);
    let rows = Array.isArray(value) ? value.concat() : [];

    rows.splice(editIndex, 1, editData);
    setValue(rows);
    this.cancelEdit();
  }

  cancelEdit() {
    this.setState({
      editIndex: -1
    });
  }

  removeRow(index = 0) {
    const {
      getValue,
      setValue
    } = this.props;

    let value = getValue();
    isPlainObject(value) && (value = [value]);
    let rows = Array.isArray(value) ? value.concat() : [];
    const toRemoved = rows[index];
    const fn = () => {
      rows.splice(index, 1);
      setValue(rows);
    };
    if (isEmptyObject(toRemoved)) {
      fn()
    } else {
      confirm('确定要删除？').then(fn);
    }
  }

  handleChange(item) {
    this.setState({
      editData: assign({}, item)
    });
  }

  render() {
    let {
      placeholder,
      inputClassName,
      $path,
      addButtonClassName,
      data,
      onNotify,
      disabled,
      formItemValue: value,
      addable
    } = this.props;
    isPlainObject(value) && (value = [value]);
    let rows = Array.isArray(value) ? value : [];
    const editData = this.state.editData;

    return (
      <div className={inputClassName}>
        <ComboForm onChange={this.handleChange} data={this.state.editData}>
          {render(`${$path}/table`, {
            type: "table",
            placeholder: (!rows || !rows.length) && addable ? (<a onClick={() => this.insertRow()} className={cx('btn', addButtonClassName)}><i className="fa fa-plus" /></a>) : placeholder,
            columns: this.state.columns
          }, {
            rows,
            data,
            editData,
            onNotify,
            disabled,
            editIndex: this.state.editIndex
          })}
        </ComboForm>
      </div>
    )
  }
}
